set_bit(vector,PSCBX(vcpu,irr));
PSCB(vcpu,pending_interruption) = 1;
}
+
+ /* Keir: I think you should unblock when an interrupt is pending. */
+ {
+ int running = test_bit(_VCPUF_running, &vcpu->vcpu_flags);
+ vcpu_unblock(vcpu);
+ if ( running )
+ smp_send_event_check_cpu(vcpu->processor);
+ }
}
void early_tick(VCPU *vcpu)
static inline void evtchn_notify(struct vcpu *v)
{
+ /*
+ * NB1. 'vcpu_flags' and 'processor' must be checked /after/ update of
+ * pending flag. These values may fluctuate (after all, we hold no
+ * locks) but the key insight is that each change will cause
+ * evtchn_upcall_pending to be polled.
+ *
+ * NB2. We save VCPUF_running across the unblock to avoid a needless
+ * IPI for domains that we IPI'd to unblock.
+ */
+ int running = test_bit(_VCPUF_running, &v->vcpu_flags);
+ vcpu_unblock(v);
+ if ( running )
+ smp_send_event_check_cpu(v->processor);
}
#endif
{
struct domain *d = v->domain;
shared_info_t *s = d->shared_info;
- int running;
- /* These three operations must happen in strict order. */
+ /* These four operations must happen in strict order. */
if ( !test_and_set_bit(port, &s->evtchn_pending[0]) &&
!test_bit (port, &s->evtchn_mask[0]) &&
- !test_and_set_bit(port>>5, &v->vcpu_info->evtchn_pending_sel) )
+ !test_and_set_bit(port>>5, &v->vcpu_info->evtchn_pending_sel) &&
+ !test_and_set_bit(0, &v->vcpu_info->evtchn_upcall_pending) )
{
- /* The VCPU pending flag must be set /after/ update to evtchn-pend. */
- set_bit(0, &v->vcpu_info->evtchn_upcall_pending);
evtchn_notify(v);
-
- /*
- * NB1. 'vcpu_flags' and 'processor' must be checked /after/ update of
- * pending flag. These values may fluctuate (after all, we hold no
- * locks) but the key insight is that each change will cause
- * evtchn_upcall_pending to be polled.
- *
- * NB2. We save VCPUF_running across the unblock to avoid a needless
- * IPI for domains that we IPI'd to unblock.
- */
- running = test_bit(_VCPUF_running, &v->vcpu_flags);
- vcpu_unblock(v);
- if ( running )
- smp_send_event_check_cpu(v->processor);
}
}
*/
extern void send_guest_pirq(struct domain *d, int pirq);
-#define event_pending(_d) \
- ((_d)->vcpu_info->evtchn_upcall_pending && \
- !(_d)->vcpu_info->evtchn_upcall_mask)
+/* Note: Bitwise operations result in fast code with no branches. */
+#define event_pending(v) \
+ ((v)->vcpu_info->evtchn_upcall_pending & \
+ ~(v)->vcpu_info->evtchn_upcall_mask)
#endif /* __XEN_EVENT_H__ */
(unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
(unsigned long)(_a4), (unsigned long)(_a5), (unsigned long)(_a6))
-#define hypercall_preempt_check() (unlikely( \
- softirq_pending(smp_processor_id()) | \
- (!!current->vcpu_info->evtchn_upcall_pending & \
- !current->vcpu_info->evtchn_upcall_mask) \
+#define hypercall_preempt_check() (unlikely( \
+ softirq_pending(smp_processor_id()) | \
+ event_pending(current) \
))
/* This domain_hash and domain_list are protected by the domlist_lock. */